<?php
/**
 * Account class holds user information
 * @package Account
 * @author Urban Soban
 * @version 0.1
 * @copyright 2009 Urban Soban
 * @link http://masterplan.sobanu.net
 */

class Account {
	/**
	 * Account ID
	 * @var uint
	 */
	private $ID;

	/**
	 * Account username
	 * @var string
	 */
	private $Username;

	/**
	 * Account password
	 * Password is hashed and is unset, when object is serialized
	 * @var string
	 */
	private $Password;

	/**
	 * Account email
	 * @var string
	 */
	private $Email;

	/**
	 * Account's access layer. Layers are defined in database
	 * @var int
	 */
	private $AccessLayer = 1;

	/**
	 * Timestamp of last login
	 * @var string
	 */
	private $LastLogin = 0;

	/**
	 * Account activation status
	 * @var boolean
	 */
	private $Activated = false;

	/**
	 * Accounts activation key
	 * @var string
	 */
	private $SecretKey;

	/**
	 * Account custom flags, loaded from _flags table.
	 * Array key represents flag_name, value prepresents flag_value
	 *
	 * @var array
	 */
	private $Flags = array();

	/**
	 * Instance of MysqlHelper
	 * @var MysqlHelper
	 */
	private $MySQL;

	/**
	 * Creates new Account
	 *
	 * @param MysqlHelper $MySQL
	 * @param string $username *optional*
	 */
	function __construct(MysqlHelper $MySQL, $usernameOrID = null){
		$this->MySQL = $MySQL;

		if($usernameOrID != null){
			$this->loadData($usernameOrID);
		}
	}

	function __wakeup(){
		$this->MySQL->connect();
		$this->logPresence();

		if(isset($this->ID)){
			$this->loadData($this->Username);
		}
	}

	/**
	 * Loads account data from database
	 *
	 * @param string $username
	 * @return boolean
	 */
	function loadData($usernameOrID){
		// Get primary account data
		if(is_numeric($usernameOrID)){
			$Sql = "SELECT * FROM {$this->MySQL->getPrefix()}accounts WHERE id = $usernameOrID";
		}
		else {
			$Sql = "SELECT * FROM {$this->MySQL->getPrefix()}accounts WHERE username = '$usernameOrID'";
		}

		$SelectAccount = $this->MySQL->query($Sql);

		if(mysql_num_rows($SelectAccount) != 1){
			return false;
		}

		$FetchAccount = mysql_fetch_assoc($SelectAccount);

		// Set primary account data
		$this->ID = $FetchAccount["id"];
		$this->Username = $FetchAccount["username"];
		$this->Password = $FetchAccount["password"];
		$this->Email = $FetchAccount["email"];
		$this->AccessLayer = $FetchAccount["access"];
		$this->LastLogin = $FetchAccount["last_login"];
		$this->Activated = ($FetchAccount["activated"] == "true") ? true : false;
		$this->SecretKey = $FetchAccount["secret_key"];

		// Get secondary account data
		$SelectFlags = $this->MySQL->query("SELECT * FROM {$this->MySQL->getPrefix()}flags WHERE flag_key = 'account_id={$this->ID}'");

		if(mysql_num_rows($SelectFlags) < 1){
			return true;
		}

		while ($Flag = mysql_fetch_assoc($SelectFlags)) {
			$this->Flags[$Flag["flag_name"]] = $Flag["flag_value"];
		}

		return true;
	}

	/**
	 * Updates or creates account.
	 * If non-existing username is given, new account is created.
	 * Account details can be updated, the ones you don't want to change can be left empty (null)
	 *
	 * @param string $username
	 * @param string $password *optional*
	 * @param string $email *optional*
	 * @param int $access_layer *optional*
	 * @param boolean $activated *optional*
	 * @param array $flags *optional*
	 * @return boolean true on success, false on failure
	 */
	function updateAccount($username, $password = null, $email = null, $access_layer = 1, $activated = false, array $flags = array()){

		if(!$this->ID){
			$CheckAvalibility = $this->MySQL->query("SELECT * FROM {$this->MySQL->getPrefix()}accounts WHERE username = '$username'");

			if(mysql_num_rows($CheckAvalibility) > 0){
				return false;
			}

			if($email == null || $password == null){
				return false;
			}

			$Secret_key = rand(00000001,99999999);
			$Registred = time();

			$Sql = "INSERT INTO {$this->MySQL->getPrefix()}accounts (username, password, email, registred, secret_key, activated, access) VALUES('$username', '$password', '$email', '$Registred', '$Secret_key', 'false', '$access_layer')";
		}
		else {
			$Sql = $this->MySQL->generateUpdateQuery($this->MySQL->getPrefix()."accounts", array("username" => $username, "password" => $password, "email" => $email, "activated" => $activated, "access" => $access_layer), array("id" => $this->ID), true);
		}

		$this->MySQL->query($Sql);

		$this->loadData($username);
		$this->updateFlags($flags);

		return true;
	}

	/**
	 * Updates _flags table in database or adds new flags if they don't exist yet.
	 *
	 * @param array $flags
	 * @return boolean true on success, false on failure
	 */
	function updateFlags(array $flags){
		if(count($flags) > 0){
			foreach ($flags as $flagName => $flagValue){
				$CheckFlagAvalibility = $this->MySQL->query("SELECT * FROM {$this->MySQL->getPrefix()}flags WHERE flag_key = 'account_id={$this->ID}' AND flag_name = '$flagName'");

				if(mysql_num_rows($CheckFlagAvalibility) > 0){
					$Sql = $this->MySQL->generateUpdateQuery($this->MySQL->getPrefix()."flags", array("flag_value" => $flagValue), array("flag_key" => "account_id=$this->ID", "flag_name" => "$flagName"));
				}
				else {
					$Sql = "INSERT INTO {$this->MySQL->getPrefix()}flags (flag_key, flag_name, flag_value) VALUES('account_id={$this->ID}', '$flagName', '$flagValue')";
				}
			}

			$this->MySQL->query($Sql);
		}
		else {
			return false;
		}

		$this->loadData($this->Username);

		return true;
	}

	/**
	 * Updates last_login filed in table _accounts with current timestamp
	 *
	 * @return boolean
	 */
	function logPresence(){
		$Update = $this->MySQL->generateUpdateQuery($this->MySQL->getPrefix()."accounts", array("last_login" => time()), array("id" => $this->ID));

		$this->MySQL->query($Update);
		return true;
	}

	/**
	 * Checks if account has been activated yet
	 *
	 * @return boolean
	 */
	function isActivated(){
		if($this->Activated == true){
			return true;
		}

		return false;
	}

	/**
	 * Returns account ID
	 * @return int
	 */
	function getID(){
		return $this->ID;
	}

	/**
	 * Returns username
	 * @return string
	 */
	function getUsername(){
		return $this->Username;
	}

	/**
	 * Returns hashed password
	 * @return string
	 */
	function getPassword(){
		return $this->Password;
	}

	/**
	 * Returns email
	 * @return string
	 */
	function getEmail(){
		return $this->Email;
	}

	/**
	 * Returns access layer
	 * @return int
	 */
	function getAccess(){
		if(!is_numeric($this->AccessLayer)){
			return 0;
		}
		else {
			return $this->AccessLayer;
		}
	}

	/**
	 * Returns timestamp of last login
	 * @return string
	 */
	function getLastLogin(){
		return $this->LastLogin;
	}

	function getSecretKey(){
		return $this->SecretKey;
	}

	/**
	 * Returns flag value of given key
	 *
	 * @param string $key
	 * @return string|boolean
	 */
	function getFlag($key){
		if(isset($this->Flags[$key])){
			return $this->Flags[$key];
		}
		return false;
	}
}

?>